<?php

/**
 * Генератор паролей.
 *
 */
abstract class Security_Utils_Password {

    /**
     * Символы для создания нормального, стойкого пароля.
     *
     * @var array
     */
    static private $_strong = array(
        'a','b','c','d','e','f','g','h','i','j','k','l','m',
        'n','o','p','q','r','s','t','u','v','w','x','y','z',
        'A','B','C','D','E','F','G','H','I','J','K','L','M',
        'N','O','P','Q','R','S','T','U','V','w','X','Y','Z',
        '1','2','3','4','5','6','7','8','9','0',
    );

    /**
     * Символы букв для создания произносимого пароля.
     *
     * @var array
     */
    static private $_pronounceable = array(
        array(
            'b', 'c', 'd', 'f', 'g', 'h', 'k', 'm',
            'n', 'p', 'r', 's', 't', 'v', 'w', 'z'
        ),
        array(
            'a', 'e', 'i', 'o', 'u','y',
        ),
    );

    /**
     * Генерирует пароль указанной длины
     *
     * @param   integer $length
     * @return  string
     */
    static public function generate($length, $pronounceable) {
        return $pronounceable ? self::_pronounceable($length) : self::_strong($length);
    }

    /**
     * Генерирует произносимый пароль указанной длины.
     *
     * @param   integer $length
     * @return  string
     */
    static public function _pronounceable($length) {
        $stack = array();

        // количество цифр — приблизительно треть от полной длины пароля
        $digits = floor($length / 3 + rand(0, 1));

        // собираем буквы
        for ($i = 0; $i < $length - $digits; $i++) {
            $stack[] = self::$_pronounceable[$i % 2][array_rand(self::$_pronounceable[$i % 2])];
        }

        // собираем цифры
        for ($i = 0; $i < $digits; $i++) {
            $stack[] = rand(0, 9);
        }

        return ucfirst(implode($stack));
    }

    /**
     * Генерирует стойкий пароль указанной длины.
     *
     * @param   integer $length
     * @return  string
     */
    static public function _strong($length) {
        $stack = array();

        for ($i = 0; $i < $length ; $i++) {
            $stack[] = self::$_strong[array_rand(self::$_strong)];
        }

        return implode($stack);
    }
}
